package com.zeyu.framework.core.persistence.table;

import org.apache.commons.lang3.builder.ToStringBuilder;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 封装web请求的DataTable的对象，为了接口的统一，都封装成一样的格式返回
 * <p/>
 * <pre>
 * 目前支持DataTable格式的数据表格,其它表格请另行开发对应数据格式:
 * 		如果是本地模式:
 * 			只需要设置data属性就好
 * 		如果是远程模式:
 * 			draw:            主要是页面翻页和缓存使用，需要根据客户端传递的值设置回去
 * 			recordsTotal:    总条数
 * 			recordsFiltered: 过滤条数,不存在可以不设置,会返回总条数
 * 			data:  		         数据对象列表
 * </pre>
 * <p/>
 * *
 * <p>
 * Wrapper object the response that must be sent back to Datatables to update
 * the table when server-side processing is enabled.
 * </p>
 * <p>
 * Since Datatables only support JSON at the moment, this bean must be converted
 * to JSON by the server.
 * </p>
 *
 * @param <T> the generic type
 * @author zeyuphoenix
 */
public class TableData<T> implements Serializable {

    /**
     * The Constant serialVersionUID.
     */
    private static final long serialVersionUID = 1L;

    /**
     * The draw.
     */
    private int draw = 1;

    /**
     * The records total.
     */
    private long recordsTotal = 0;

    /**
     * The records filtered.
     */
    private long recordsFiltered = 0;

    /**
     * The data.
     */
    private List<T> data = new ArrayList<>();

    /**
     * 构造函数
     *
     * @param data      数据项目
     * @param criterias 客户端参数
     */
    private TableData(List<T> data, long recordsTotal, long recordsFiltered,
                      DatatablesCriterias criterias) {
        this.data = data;
        this.recordsTotal = recordsTotal;
        this.recordsFiltered = recordsFiltered;
        this.draw = criterias.getDraw();
    }

    /**
     * 构造函数 普通表格
     *
     * @param data 数据项目
     */
    private TableData(List<T> data, long recordsTotal) {
        this.data = data;
        this.recordsTotal = recordsTotal;
    }

    /**
     * build 数据
     */
    public static <T> TableData<T> build(List<T> data, long recordsTotal,
                                         long recordsFiltered, DatatablesCriterias criterias) {
        return new TableData<>(data, recordsTotal, recordsFiltered, criterias);
    }

    /**
     * build 数据
     */
    public static <T> TableData<T> build(List<T> data, long recordsTotal,
                                         DatatablesCriterias criterias) {
        return new TableData<>(data, recordsTotal, recordsTotal, criterias);
    }

    /**
     * build 数据
     */
    public static <T> TableData<T> build(List<T> data, long recordsTotal) {
        return new TableData<>(data, recordsTotal);
    }

    /**
     * Gets the draw.
     *
     * @return the draw
     */
    public int getDraw() {
        return draw;
    }

    /**
     * Sets the draw.
     *
     * @param draw the new draw
     */
    public void setDraw(int draw) {
        this.draw = draw;
    }

    /**
     * Gets the records total.
     *
     * @return the records total
     */
    public long getRecordsTotal() {
        return recordsTotal;
    }

    /**
     * Sets the records total.
     *
     * @param recordsTotal the new records total
     */
    public void setRecordsTotal(long recordsTotal) {
        this.recordsTotal = recordsTotal;
    }

    /**
     * Gets the records filtered.
     *
     * @return the records filtered
     */
    public long getRecordsFiltered() {
        if (this.recordsFiltered <= 0) {
            return recordsTotal;
        }
        return recordsFiltered;
    }

    /**
     * Sets the records filtered.
     *
     * @param recordsFiltered the new records filtered
     */
    public void setRecordsFiltered(long recordsFiltered) {
        this.recordsFiltered = recordsFiltered;
    }

    /**
     * Gets the data.
     *
     * @return the data
     */
    public List<T> getData() {
        return data;
    }

    /**
     * Sets the data.
     *
     * @param data the new data
     */
    public void setData(List<T> data) {
        this.data = data;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}
